﻿using Core.DataAccess.Model.Projects;
using Core.Framework.Model.Common;
using Core.Framework.Redis.Queue_Helper;
using Core.Framework.Util;
using Core.IBusiness.ILoggerModule;
using Core.IBusiness.IProjectModule;
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;

namespace Core.Middleware.ApiRelationUrl
{
    public class ApiRelationUrlMidWare
    {
        /// <summary>
        /// 项目服务
        /// </summary>
        private IProject iProject { get; set; }

        //private ILog iLog = BuildServiceProvider.GetService<ILog>();

        private readonly RequestDelegate requestDelegate;

        public ApiRelationUrlMidWare(RequestDelegate requestDelegate)
        {
            this.iProject = BuildServiceProvider.GetService<IProject>();
            this.requestDelegate = requestDelegate;
        }

        public async Task Invoke(HttpContext context)
        {

            //context.Request.Host = new HostString("hsrs.itool.store");
            //context.Request.Host = new HostString("maopu.itool.com");
            //context.Request.Host = new HostString("api.microsoft.itool.store");


            System.IO.File.AppendAllText($"requst.txt", 
                $" {DateTime.Now} \n {context.Request.Host.ToString()} \n{context.Request.Path.ToString()} \n\n");



            var projectInfo = this.GetProjectInfo(context.Request.Host.ToString());

            this.Connection(context);

            if (projectInfo == null)
            {
                return;
            }

            //iLog.DeBug<ApiRelationUrlMidWare>($"url:{context.Request.Path.ToString()},Host:{context.Request.Host.ToString()}", projectInfo.Token);


            context.Items.Add("ApiProjectInfo", projectInfo);

            this.TrySetUserClientInfo(context);

            await requestDelegate(context);
        }

        #region 项目信息

        /// <summary>
        /// 获取项目信息
        /// </summary>
        /// <param name="scheme"></param>
        /// <returns></returns>
        private ApiProjectInfo GetProjectInfo(string scheme)
        {

            var result = RedisQueueHelper.HashGet(RedisQueueHelperParameter.ApiProjectInfo, scheme);

            if (string.IsNullOrWhiteSpace(result))
            {
                var info = this.QueryProjectInfo(scheme);

                if (info == null)
                {
                    RedisQueueHelper.HashSet(RedisQueueHelperParameter.ApiProjectInfo, scheme, "false");
                }
                else
                {
                    RedisQueueHelper.HashSet(RedisQueueHelperParameter.ApiProjectInfo, scheme, info.TryToJson());
                }

                return info;
            }
            else if ("false" == result) 
            {
                return null;
            }

            return ((string)result).TryToEntity<ApiProjectInfo>();
        }

        /// <summary>
        /// 查询项目信息
        /// </summary>
        /// <returns></returns>
        private ApiProjectInfo QueryProjectInfo(string scheme)
        {
            var result = iProject.GetProjectInfoAndPayInfoByScheme(scheme);

            if (!result.IsFinished)
            {
                return null;
            }

            // 构造存储容器
            var info = new ApiProjectInfo
            {
                Key = result.Date.Id,
                UserKey = result.Date.UserKey,
                Title = result.Date.Title,
                Token = result.Date.Token
            };

            if (result.Date.AliPayInfo != null)
            {
                info.PayAliInfo = new PayAliInfo
                {
                    ApiUrl = result.Date.AliPayInfo.ApiUrl,
                    AppId = result.Date.AliPayInfo.AppCode,
                    Privtekey = result.Date.AliPayInfo.Privtekey,
                    Publickey = result.Date.AliPayInfo.Publickey,

                    MinAppId = result.Date.AliPayInfo.MinAppId,
                    MinPrivtekey = result.Date.AliPayInfo.MinPrivtekey,
                    MinPublickey = result.Date.AliPayInfo.MinPublickey,

                    PayeeAccount = result.Date.AliPayInfo.PayeeAccount,
                    PayeeRealName = result.Date.AliPayInfo.PayeeRealName
                };
            }

            if (result.Date.WChatPayInfo != null)
            {
                info.PayWChatInfo = new PayWChatInfo
                {
                    ApiUrl = result.Date.WChatPayInfo.ApiUrl,
                    AppId = result.Date.WChatPayInfo.AppCode,
                    ApiKey = result.Date.WChatPayInfo.ApiKey,
                    MchId = result.Date.WChatPayInfo.MchId,
                    NotifyUrl = result.Date.WChatPayInfo.NotifyUrl,

                    MinAppId = result.Date.WChatPayInfo.MinAppId,
                    MinSecret = result.Date.WChatPayInfo.MinSecret
                };
            }

            return info;
        }

        /// <summary>
        /// Connection 数据处理
        /// </summary>
        private void Connection(HttpContext context)
        {
            var ip = context.Connection.RemoteIpAddress.ToString();
            context.Response.Headers["address"] = ip;
            context.Items["RemoteIpAddress"] = ip;
        }

        #endregion

        #region 用户身份信息

        /// <summary>
        /// 尝试写入用户身份信息
        /// </summary>
        /// <param name="context"></param>
        private void TrySetUserClientInfo(HttpContext context) 
        {
            var client = this.GetApiClientInfoByHeaders(context.Request.Headers);


            //var projectInfo = (ApiProjectInfo)context.Items["ApiProjectInfo"];
            //iLog.DeBug<ApiRelationUrlMidWare>($"client:{client.TryToJson()}", projectInfo.Token);

            if (client != null)
            {
                context.Items.Add("ClientInfo", client);
            }

        }



        /// <summary>
        /// 获取用户身份信息
        /// </summary>
        /// <param name="Headers"></param>
        /// <returns></returns>
        private ApiClientInfo GetApiClientInfoByHeaders(IHeaderDictionary Headers)
        {

            // Item1 = Token, Item2 = isDebug
            var headers = this.GetTokenAndIsDebugByHeader(Headers);

            // Item1 = ApiClientInfo, Item2 = ProjectUser
            var clientInfo = this.GetClientInfoByToken(headers.Item1);


            // 获取用户身份信息
            var client = clientInfo.Item1;

            if (null == clientInfo.Item1)
            {
                if (null == clientInfo.Item2) return client;

                if (headers.Item2)
                    client = this.GetApiClientInfoByDebugAdminInfo(clientInfo.Item2);
                else
                    client = this.GetApiClientInfoByAdminInfo(clientInfo.Item2);
            }
            else
            {
                // 构造用户签名
                client.Token = headers.Item1;
                client.clientType = this.GetClientTypeByHeader(Headers);
            }

            return client;
        }

        /// <summary>
        /// 获取Token和IsDebug请求头信息
        /// </summary>
        /// <param name="Headers"></param>
        /// <returns></returns>
        private Tuple<string, bool> GetTokenAndIsDebugByHeader(IHeaderDictionary Headers)
        {
            // 用户身份签名
            string token = Headers["itool-token"].ToString();
            // 是否是Debug项目
            bool isDebug = !string.IsNullOrWhiteSpace(Headers["itool-isdebug"].ToString());

            return new Tuple<string, bool>(token, isDebug);
        }

        /// <summary>
        /// 获取客户端类型
        /// </summary>
        /// <param name="Headers"></param>
        /// <returns></returns>
        private ClientTypeEnum GetClientTypeByHeader(IHeaderDictionary Headers)
        {
            ClientTypeEnum result = ClientTypeEnum.None;
            string type = Headers["itool-clienttype"].ToString();
            switch (type)
            {
                case "h5":
                    result = ClientTypeEnum.H5;
                    break;
                case "wchat":
                    result = ClientTypeEnum.WChat;
                    break;
                case "ali":
                    result = ClientTypeEnum.ALI;
                    break;
                case "app":
                    result = ClientTypeEnum.App;
                    break;
            }

            return result;

        }

        /// <summary>
        /// 从Redis获客户端信息
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        private Tuple<ApiClientInfo, ProjectUser> GetClientInfoByToken(string token)
        {
            var client = ((string)RedisQueueHelper.HashGet(RedisQueueHelperParameter.ApiClientByToken, token))
                .TryToEntity<ApiClientInfo>();

            var project = default(ProjectUser);

            if (null == client)
            {
                // 尝试获取项目用户信息
                project = ((string)RedisQueueHelper.HashGet(RedisQueueHelperParameter.ProjectUserLogin, token, 15))
                    .TryToEntity<ProjectUser>();
            }

            return new Tuple<ApiClientInfo, ProjectUser>(client, project);
        }

        /// <summary>
        /// 管理员身份信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        private ApiClientInfo GetApiClientInfoByAdminInfo(ProjectUser user)
        {
            return new ApiClientInfo
            {
                Key = 1,
                Token = "system",
                UserName = "Admin",
                EndTime = DateTime.Now.AddDays(1)
            };
        }

        /// <summary>
        /// Debug身份信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        private ApiClientInfo GetApiClientInfoByDebugAdminInfo(ProjectUser user)
        {
            return new ApiClientInfo
            {
                Key = user.Id + 100000,
                Token = user.Token,
                UserName = user.UserName,
                EndTime = DateTime.Now.AddDays(1)
            };
        }


        #endregion
    }
}
